use std::str::FromStr;

use chrono::Local;
use sea_orm::{
    ActiveModelTrait, ColumnTrait, EntityTrait, NotSet, PaginatorTrait, QueryFilter, QueryOrder,
};
use sea_orm::ActiveValue::Set;

use common::ctx::get_db;
use common::error::MyError;
use common::page::{BasePage, PageResult};
use entity::prelude::SysDictGroup;
use entity::sys_dict_group;
use model::dict::{CreateDictGroup, DictGroupPage};

use crate::manager::base::BaseManager;
use crate::manager::dict::DictManager;

pub struct DictGroupManager {}

impl BaseManager<i64, sys_dict_group::Model, DictGroupPage, CreateDictGroup, sys_dict_group::Model>
    for DictGroupManager
{
    async fn list() -> Result<Vec<sys_dict_group::Model>, MyError> {
        let list = SysDictGroup::find().all(&*get_db()?).await?;
        Ok(list)
    }

    async fn page(page: DictGroupPage) -> Result<PageResult<sys_dict_group::Model>, MyError> {
        let mut find = SysDictGroup::find();
        //排序
        if let Some(sorter) = page.get_order() {
            let field = sys_dict_group::Column::from_str(sorter.field.as_str()).or_else(|e| {
                Err(MyError::DBError(format!(
                    "获取排序字段失败：{}",
                    e.to_string()
                )))
            })?;
            find = find.order_by(field, sorter.order());
        }

        //校验并获取分页数据
        let page_data = page.check_page_data();
        //每页大小
        let db_conn = &*get_db()?;
        let paginator = find.paginate(db_conn, page_data.page_size);

        //执行分页查询
        let record = paginator.fetch_page(page_data.page - 1).await?;
        //总条数
        let total = paginator.num_items().await?;
        //返回分页结果
        Ok(PageResult {
            page: page_data.page,
            page_size: page_data.page_size,
            total,
            record,
        })
    }

    async fn info(id: i64) -> Result<Option<sys_dict_group::Model>, MyError> {
        Ok(SysDictGroup::find_by_id(id).one(&*get_db()?).await?)
    }

    async fn add(form: CreateDictGroup) -> Result<i64, MyError> {
        let group_name = form
            .group_name
            .ok_or(MyError::ServerError("group_name不能为空".to_string()))?;
        let group_code = Local::now().timestamp_millis().to_string();
        let model = sys_dict_group::ActiveModel {
            id: NotSet,
            group_name: Set(Some(group_name)),
            group_code: Set(Some(group_code)),
            default: Default::default(),
        }
        .insert(&*get_db()?)
        .await?;
        Ok(model.id)
    }

    async fn update(form: sys_dict_group::Model) -> Result<i64, MyError> {
        let entity = SysDictGroup::find_by_id(form.id)
            .one(&*get_db()?)
            .await?
            .ok_or(MyError::ServerError(format!(
                "user [{:?}] does not exist",
                form.id
            )))?;
        let mut entity: sys_dict_group::ActiveModel = entity.into();
        if form.group_name.is_some() {
            entity.group_name = Set(form.group_name);
        }
        let result = entity.update(&*get_db()?).await?;
        Ok(result.id)
    }

    async fn delete(id: i64) -> Result<bool, MyError> {
        let dict_list = DictManager::get_by_group_id(id).await?;
        if dict_list.is_empty() {
            let res = SysDictGroup::delete_by_id(id).exec(&*get_db()?).await?;
            Ok(res.rows_affected == 1)
        } else {
            Err(MyError::ServerError("分组下存在字典无法删除".to_string()))
        }
    }
}

impl DictGroupManager {
    pub async fn search_list(page: DictGroupPage) -> Result<Vec<sys_dict_group::Model>, MyError> {
        let mut find = SysDictGroup::find();
        if let Some(group_name) = page.group_name {
            find = find.filter(sys_dict_group::Column::GroupName.like(format!("%{}%", group_name)));
        }
        Ok(find.all(&*get_db()?).await?)
    }
}
